/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights
 * reserved. <a>http://www.cqcis.com</a>
 */
package com.cqcis.uip.base.framework.base.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.cqcis.uip.base.framework.UIPServiceException;
import com.cqcis.uip.base.framework.UIPTaskException;
import com.cqcis.uip.base.framework.base.AbstractAcceptorSupport;
import com.cqcis.uip.base.framework.codec.text.HttpProtocolDecoder;
import com.cqcis.uip.base.framework.codec.text.HttpProtocolEncoder;
import com.cqcis.uip.base.framework.common.HttpParam;
import com.cqcis.uip.base.framework.common.Role;
import com.cqcis.uip.base.framework.common.Task;
import com.cqcis.uip.base.framework.common.HttpParam.ParamContent;
import com.cqcis.uip.base.framework.core.RegisteredServiceContext;
import com.cqcis.uip.base.framework.core.Service;
import com.cqcis.uip.base.framework.core.ServiceRole;
import com.cqcis.uip.base.framework.core.ServiceRoleIgnore;
import com.cqcis.uip.base.framework.core.impl.AcceptorServiceAdaptor;
import com.cqcis.uip.base.framework.handlers.CommonService;
import com.cqcis.uip.base.framework.handlers.HttpServerService;
import com.cqcis.uip.base.framework.handlers.ServerService;
import com.cqcis.uip.base.framework.handlers.impl.DefaultServerHandler;

/**
 * @author huangmy
 * @date   2008-12-4
 */
@ServiceRoleIgnore
public class DefaultHttpAcceptorStub extends AbstractAcceptorSupport {
	private static final long serialVersionUID = 1L;
	private static Log log = LogFactory.getLog(DefaultHttpAcceptorStub.class);
    private AcceptorServiceAdaptor serviceAdaptor;
    private DefaultCommoner commoner;
    private RegisteredServiceContext serviceContext; // serviceContext
    private HttpServerService httpservice; // httpservice
    
    @Override
    public void start(RegisteredServiceContext serviceContext) throws Exception {
    	init(); // init first
    	this.serviceContext = serviceContext;
    	
    	super.start(serviceContext);
    	
    	if (serviceAdaptor.getService() instanceof CommonService) {
    		CommonService service = (CommonService)serviceAdaptor.getService();
    		this.commoner = new DefaultCommoner();
    		this.commoner.setBundleContext(this.bundleContext);
    		this.commoner.registerLogConfiguration(this.getLogConfiguration());
    		this.commoner.setCommonService(service);
    		this.commoner.setEndpointExpression(this.endpointExpression);
    		this.commoner.setInterfaceId(this.interfaceId);
    		this.commoner.setInterfaceName(this.interfaceName);
    		this.commoner.setIntervalTime(this.intervalTime);
    		this.commoner.setLogDir(this.logDir);
    		this.commoner.setLogLevel(this.logLevel);
    		this.commoner.setStreamLogOutputService(this.streamLogOutputService);
    		this.commoner.setThreadNumberExtendTaskResultProcessor(this.threadNumberExtendTaskResultProcessor);
    		this.commoner.setThreadNumberSchedule(this.threadNumberTaskDispatcher);
    		this.commoner.setThreadNumberTaskDispatcher(this.threadNumberTaskDispatcher);
    		this.commoner.setToEndpointExpression(this.toEndpoint.getExpression());
    		this.commoner.setThreadNumberTaskResultDispatcher(this.threadNumberTaskResultDispatcher);
    		this.commoner.setWaitTaskMax(this.waitTaskMax);
    		
    		this.commoner.start(serviceContext);
    	}
    	
    	if (httpservice instanceof Service) {
			((Service)httpservice).start(serviceContext);
		}
    }
    
    @Override
    public void stop(RegisteredServiceContext serviceContext) throws Exception {
    	if (this.commoner != null) {
    		this.commoner.stop(serviceContext);
    	}
    	super.stop(serviceContext);
    	
    	if (httpservice instanceof Service) {
			((Service)httpservice).stop(serviceContext);
		}
    }
    
    private void init() {    	
    	DefaultServerHandler handler = new DefaultServerHandler();    	
    	handler.setBeforeService(serviceAdaptor.getBeforeService());//预处理
    	handler.setService(serviceAdaptor.getService());// 业务层处理
    	
    	setHandler(handler);
    	
    	setDecoder(new HttpProtocolDecoder()); //读数据解码器 
    	setEncoder(new HttpProtocolEncoder()); //写数据编码器
    	
    	if (serviceAdaptor.getReadFilters() != null) {
    		setReadFilters(serviceAdaptor.getReadFilters());
    	}
    	
    	if (serviceAdaptor.getWriteFilters() != null) {
    		setWriteFilters(serviceAdaptor.getWriteFilters());
    	}
    }
    
    @Override
    protected boolean doSchedule() {
    	return doScheduleSync(getTaskQueue().poll());
    }
    
    @Override
    protected boolean doScheduleSync(Task task) {
    	if (this.commoner == null) {
			throw new UIPServiceException("the service maybe not implements CommonService.");
		}
    	try {
			return this.commoner.scheduleSync(task);
		} catch (Exception e) {
			throw new UIPTaskException(e);
		}
    }
	
	@Override
	protected void doStart() throws Exception {
		// do nothing		
	}

	@Override
	protected void doStop() throws Exception {
		// do nothing		
	}
    
	@ServiceRole(Role.HTTP_SERVER)
	public void setHttpServService(final HttpServerService httpservice) {
		AcceptorServiceAdaptor serviceAdaptor = new AcceptorServiceAdaptor();
		
		this.httpservice = httpservice;
				
		serviceAdaptor.setService(new ServerService() {
			public Object doMessageReceived(Object message) throws Exception {
				HttpParam input = (HttpParam)message;
				HttpParam p = null;
				
				try {
					p = httpservice.doMessageReceived(input);
					if (p != null) {
						withHttpParams(p);
						p.setSession(input.getSession());
						p.setAttribute(HttpParam.STREAM_LOG_OUT_SERVICE, 
								serviceContext.getStreamLogOutputService());
					} else {
						log.error("doMessageReceived can't return null.");
						p = new HttpParam();
						p.setHeaderline("HTTP/1.1 500 Internal Server Error");
						withHttpParams(p);
						p.setSession(input.getSession());
						p.setAttribute(HttpParam.STREAM_LOG_OUT_SERVICE, 
								serviceContext.getStreamLogOutputService());
					}			
				} catch (Throwable e) {
					p = new HttpParam();
					p.setHeaderline("HTTP/1.1 500 Internal Server Error");
					withHttpParams(p);
					p.setSession(input.getSession());
					p.setAttribute(HttpParam.STREAM_LOG_OUT_SERVICE, 
							serviceContext.getStreamLogOutputService());
					log.error("Catch Exception in doMessageReceived.", e);
				}
				
				return p;
			}
		});
		
		this.serviceAdaptor = serviceAdaptor;
	}
	
	@Override
	public Role getRole() {
		return Role.HTTP_SERVER;
	}
	
	private void withHttpParams(HttpParam p) {
		p.addParams(new ParamContent(HttpParam.SERVER, "UIP-v1.0"));
		p.addParams(new ParamContent(HttpParam.X_POWERED_BY, "UIP-v1.0"));
				
		// Date
		p.addParams(new ParamContent(HttpParam.DATE, new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss 'GMT'", Locale.ENGLISH).format(new Date())));
		
		// close
		if (!isKeepAlive()) {
			p.addParams(new ParamContent(HttpParam.CONNECTION, "close"));
		}
	}
}
